
module axi_sram_controller #(
  parameter DATA_WIDTH  = 8,
  parameter ADDR_WIDTH  = 16,
  parameter BANK_BITS   = 6
)(
  input clk,
  input rst_n,

  // AXI Write Interface
  input [ADDR_WIDTH-1:0] awaddr,
  input awvalid,
  output reg awready,

  input [DATA_WIDTH-1:0] wdata,
  input wvalid,
  output reg wready,

  output reg [1:0] bresp,
  output reg bvalid,
  input bready,

  // SRAM Interface
  output reg [ADDR_WIDTH-1:0] sram_addr,
  output reg [DATA_WIDTH-1:0] sram_din,
  output reg [BANK_BITS-1:0] bank_sel,
  output reg cs,
  output reg wen
);

  // 状态机定义
  typedef enum logic [1:0] {
    IDLE,       // 0
    ADDR_PHASE, // 1
    DATA_PHASE, // 2
    RESP_PHASE  // 3
  } state_t;
  
  state_t state;

  // 寄存器定义
  reg [BANK_BITS-1:0] curr_bank;
  reg [63:0] bank_busy;
  reg [ADDR_WIDTH-1:0] latched_awaddr;
  reg [DATA_WIDTH-1:0] latched_wdata;
  reg resp_error;

  // 主状态机
  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      state <= IDLE;
      awready <= 1'b1;
      wready <= 1'b1;
      bvalid <= 1'b0;
      cs <= 1'b0;
      wen <= 1'b1;
      bank_busy <= 64'h0;
      latched_awaddr <= {ADDR_WIDTH{1'b0}};
      latched_wdata <= {DATA_WIDTH{1'b0}};
      resp_error <= 1'b0;
    end else begin
      case (state)
        // IDLE状态：等待地址和数据同步到达
        IDLE: begin
          awready <= 1'b1;  // 持续置高
          wready <= 1'b1;
          
          if (awvalid && awready) begin
            latched_awaddr <= awaddr;
            awready <= 1'b0;  // 锁存地址后停止接收新地址
          end
          
          if (wvalid && wready) begin
            latched_wdata <= wdata;
            wready <= 1'b0;   // 锁存数据后停止接收新数据
          end
          
          // 当地址和数据均已锁存且Bank空闲时触发状态转换
          if (!awready && !wready && !bank_busy[latched_awaddr[15:10]]) begin
            state <= ADDR_PHASE;
            bank_sel <= latched_awaddr[15:10];
            curr_bank <= latched_awaddr[15:10];
          end
        end

        // 地址相位：驱动SRAM接口
        ADDR_PHASE: begin
          sram_addr <= latched_awaddr;
          sram_din <= latched_wdata;
          cs <= 1'b1;
          wen <= 1'b0; // 写使能有效
          bank_busy[curr_bank] <= 1'b1; // 标记bank为忙
          state <= DATA_PHASE;
        end

        // 数据相位：保持信号
        DATA_PHASE: begin
          cs <= 1'b0;
          wen <= 1'b1;
          bvalid <= 1'b1;
          state <= RESP_PHASE;
        end

        // 响应相位：等待握手
        RESP_PHASE: begin
          if (bready) begin
            bvalid <= 1'b0;
            awready <= 1'b1;
            wready <= 1'b1;
            bank_busy[curr_bank] <= 1'b0; // 释放bank
            resp_error <= 1'b0;
            state <= IDLE;
          end
        end
      endcase
    end
  end

  // 响应生成组合逻辑
  always @(*) begin
    bresp = resp_error ? 2'b10 : 2'b00;
  end

  // 时序检查（示例）
  property check_bank_busy;
    @(posedge clk) disable iff (!rst_n)
    (state == ADDR_PHASE) |-> ##1 (bank_busy[curr_bank] == 1);
  endproperty
  assert property (check_bank_busy);

endmodule